#ifndef _PDTEXT_EXTRACTOR_H_
#define _PDTEXT_EXTRACTOR_H_

#include "FXAPI.h"

#define PDF2PDF_DEBUG1(msg) cout<<msg<<endl;

/*
	#ifndef FOXIT_DEBUG2
		#define FOXIT_DEBUG2(msg,param1) FX_OUTPUT_LOG_FUNC(msg,param1)
	#endif
	#ifndef FOXIT_DEBUG3
		#define FOXIT_DEBUG3(msg,param1,param2) FX_OUTPUT_LOG_FUNC(msg,param1,param2)
	#endif
*/
class CPDPageLineInfo
{
public:
	CPDPageLineInfo(IPDFLR_Cell* pLine);
	~CPDPageLineInfo();

	CPDF_Rect GetLineRect();
	FX_BOOL GetLineFontInfo(FX_FLOAT& fontsize, FX_DWORD& fontcolor, FX_BOOL& isCID);
	FX_BOOL IsIndependLine(FX_FLOAT page_width, FX_FLOAT page_height);

protected:
	IPDFLR_Cell* m_pLine;
};

class CPDPageParagraphInfo
{
public:
	CPDPageParagraphInfo(IPDFLR_Cell* pParagraph);
	~CPDPageParagraphInfo();

	void GetLineIndependInfo(FX_FLOAT page_width, FX_FLOAT page_height, FX_INT32& nLineCount, FX_BOOL& bAllLineIndepend);
	CFX_WideString* GetLineContent(FX_INT32 iLine){return (CFX_WideString*)m_arrLineContent.GetAt(iLine);}
	CPDF_Rect GetLineRect(FX_INT32 iLine){CPDF_Rect* p = (CPDF_Rect*)m_arrLineRect.GetAt(iLine); return *p;}
	IPDFLR_Cell* GetLineCell(FX_INT32 iLine){return (IPDFLR_Cell*)m_arrLineCell.GetAt(iLine);}
	FX_INT32 GetIndependLineCount(){return m_arrLineContent.GetSize();}
protected:
	IPDFLR_Cell* m_pParagraph;
	CFX_PtrArray m_arrLineContent;
	CFX_PtrArray m_arrLineRect;
	CFX_PtrArray m_arrLineCell;
};
struct NEWLINECONTENTINFO
{
	FX_FLOAT m_fFontSize;
	FX_DWORD m_dwFillClr;
	FX_DWORD m_dwStrokeClr;
	FX_BOOL m_bIsItalic;
	FX_INT32 m_nFontWight;
	FX_BOOL m_bIsCJK;
	FX_FLOAT m_fWordSpace;
	FX_FLOAT m_fCharSpace;
	CFX_WideString m_wsContent;

	NEWLINECONTENTINFO(){
	m_fFontSize = 1.0f;
	m_dwFillClr = m_dwStrokeClr = 0x00000000;
	m_bIsItalic = FALSE;
	m_nFontWight = 400;
	m_bIsCJK = FALSE;
	m_fWordSpace = 0.0f;
	m_fCharSpace = 0.0f;
	m_wsContent = L"";
	}
};
class CNewParagraphLayoutInfo
{
public:
	CNewParagraphLayoutInfo(CPDF_Page* pDestPage, CPDF_Font* pFont, IPDFLR_Cell* pParagraph);
	~CNewParagraphLayoutInfo();

	void CalcNewLayoutInfo(const CFX_WideString& wsContent, FX_FLOAT fWordSpace, FX_FLOAT fCharSpace);
	FX_INT32 CountLines(){return m_arrNewLineContentInfo.GetSize();}
	NEWLINECONTENTINFO* GetNewLineInfo(FX_INT32 iLine){return (NEWLINECONTENTINFO*)m_arrNewLineContentInfo.GetAt(iLine);}
	CPDF_Rect GetLineRect(FX_INT32 iLine){return *(CPDF_Rect*)m_arrLineRect.GetAt(iLine);}
	void GetParagraphRect(CPDF_Rect& rc){rc=m_rcParagraphBox;}
protected:
	void PrepareAllLineInfo(const CFX_WideString& wsContent, FX_FLOAT fWordSpace, FX_FLOAT fCharSpace);
	void AdjustLineInfo(const CFX_WideString& wsContent);
protected:
	IPDFLR_Cell* m_pParagraph;
	CPDF_Page* m_pDestPage;
	CPDF_Font* m_pFont;
	FX_BOOL m_bNeedAdjust;
	CPDF_Rect m_rcParagraphBox;

	CFX_PtrArray m_arrNewLineContentInfo;
	CFX_PtrArray m_arrLineRect;
};

class CParagraphCreator
{
public:
	CParagraphCreator(CPDF_Page* pPage, IPDFLR_Cell* pParagraph);
	~CParagraphCreator();
	FX_BOOL Create( const CFX_WideString& wsContent, CPDF_Font* pFont, FX_FLOAT fWordSpace, FX_FLOAT fCharSpace);
protected:
	CPDF_Page* m_pDestPage;
	IPDFLR_Cell* m_pParagraph;
};

/*
class CPDPageLayoutInfo
{
public:
	CPDPageLayoutInfo(CPDF_Page* pPage);
	~CPDPageLayoutInfo();

	void BuildPageInfo();

};
*/
struct INDEPENDLINEPARAGRAPH
{
	FX_INT32 m_iPage;
	FX_INT32 m_iPara;
	CPDPageParagraphInfo* m_pInfo;

	INDEPENDLINEPARAGRAPH(){
	m_iPage = -1;
	m_iPara = -1;
	m_pInfo = NULL;
	}
	~INDEPENDLINEPARAGRAPH(){
		if(m_pInfo){
			delete m_pInfo;
			m_pInfo = NULL;
		}
	}
};
class CPDTextExtractor
{
public:
	CPDTextExtractor();
	~CPDTextExtractor();
	
	FX_INT32 StartExtract(FX_LPCWSTR lpszFile, const char* pwd);
	void Close();
	
	FX_INT32 CountParagraphRects(FX_INT32 iPage);
	CPDF_Rect GetParagraphRect(FX_INT32 iPage, FX_INT32 iRect);
	FX_BOOL IsAllLineIndepend(FX_INT32 iPage, FX_INT32 iParagraph);
	FX_INT32 GetIndependLineCount(FX_INT32 iPage, FX_INT32 iParagraph);
	CFX_WideString GetIndependLineContent(FX_INT32 iPage, FX_INT32 iParagraph, FX_INT32 iLine);
	IPDFLR_Cell* GetIndependLineInfo(FX_INT32 iPage, FX_INT32 iParagraph, FX_INT32 iLine, CPDF_Rect& rc);
	
	CFX_WideString GetParagraphContent(FX_INT32 iPage, FX_INT32 iParagraph);
	
	FX_INT32 CountLineRects(FX_INT32 iPage);
	FX_RECT GetLineRect(FX_INT32 iRect);
	CFX_WideString GetLineContent(FX_INT32 iLine);
	
	CPDF_Document* GetPDDoc(){return m_pPDParser->GetDocument();}
	FX_INT32 CountPage(){return m_pPDParser->GetDocument()->GetPageCount();}
	void GetMatrix(CPDF_Matrix& mt);
	IPDFLR_DocumentProcessor* GetLRProcessor(){return m_pLRProcessor;}
	CFX_WideString GetSrcFilePath(){return m_wsSrcFilePath;}
	IPDFLR_PageProcessor* GetPageLRProcessor(FX_INT32 iPage);
	void GetObjText(CPDF_PageObject* pObj, CFX_WideString& csText);
	void ExtractParagraphContent(IPDFLR_Cell* pCell, FX_FLOAT fPageWidth, CFX_WideString& csCon);
protected:
	CPDF_Matrix* m_pDisplayMatrix;
	CPDF_Parser* m_pPDParser;
	IPDFLR_DocumentProcessor* m_pLRProcessor;
	CFX_PtrArray m_arrPageLRProcessor;
	CFX_WideString m_wsSrcFilePath;
	CFX_PtrArray m_arrIndependPara;
};
class CFX_MapPtrToPtr;
class CPDFileRebuilder
{
public:
	CPDFileRebuilder();
	~CPDFileRebuilder();
	void InitDestInfo(FX_DWORD dwCharset){m_dwCharset = dwCharset;}
	CPDF_Page* GetPage(int iPage);
	void SetTextExtractor(CPDTextExtractor* pExtractor){m_pExtractor = pExtractor;}
	CPDF_Document* CreateDoc(CPDF_Document* pPDDoc);
	FX_BOOL AddParagraph(FX_INT32 iPage, FX_INT32 iParagraph, CFX_WideString& wsContent);
	FX_BOOL AddIndependLine(FX_INT32 iPage, FX_INT32 iParagraph, FX_INT32 iLine, CFX_WideString& wsContent);
	FX_INT32 Save(CFX_WideString& wsFile);

	CPDF_Font * GetFont(FX_DWORD dwCharset);
	CPDF_Rect AddTextToPage(CPDF_Page* pPage, FX_WCHAR char_code, CPDF_Font* pFont, FX_FLOAT fontsize, FX_DWORD fontclr, FX_FLOAT x, FX_FLOAT y);
	CPDF_Rect AddTextLineToPage(CPDF_Page* pPage, const CFX_WideString& wsContent, CPDF_Font* pFont, FX_FLOAT fontsize, FX_DWORD fontclr, FX_FLOAT x, FX_FLOAT y);
protected:
	void RemovePageText(CPDF_PageObjects* pPageObjects);


protected:
	CPDTextExtractor* m_pExtractor;
	CPDF_Document* m_pSrcPDDoc;
	CPDF_Document* m_pDestDoc;
	CFX_MapPtrToPtr*	m_pMapPtrToPtr;
	CFX_PtrArray m_arrNewPages;
	CPDF_Parser* m_pPDParser;
	CPDF_Font* m_pFont;

	FX_DWORD m_dwCharset;
};

class CPDProccessor
{
public:
	CPDProccessor(){}
	~CPDProccessor(){}
	
	CPDTextExtractor m_Extractor;
	CPDFileRebuilder m_Builder;

	CFX_WideString m_wsDestPath;
	
};

//CFX_WideString gExtractParagraphContent(IPDFLR_Cell* pCell, FX_FLOAT fPageWidth);
CFX_WideString gGetObjText(CPDF_PageObject* pObj);

#define LOG_FILE "/tmp/pdf2pdf_log.txt"
void gWriteLog(CFX_ByteString bsMsg);
/*
//interface for dll export
CPDProccessor* CreateProccessor();
void CloseProcessor();

FX_INT32 StartExtract(CPDProccessor* pProccessor, FX_LPCWSTR file, const char* pwd);
FX_INT32 CountPage(CPDProccessor* pProccessor);
FX_INT32 CountParagraph(CPDProccessor* pProccessor, FX_INT32 iPage);
CFX_WideString GetParagraphContent(CPDProccessor* pProccessor, FX_INT32 iPage, FX_INT32 iParagraph);

void AddParagraph(CPDProccessor* pProccessor, FX_INT32 iPage, FX_INT32 iParagraph, CFX_WideString& content);
FX_INT32 SaveFile(CPDProccessor* pProccessor, FX_LPCWSTR file);
*/
#endif
